package us.mooresr.webtroopmanager.client.ui;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import us.mooresr.webtroopmanager.client.place.EventListPlace;
import us.mooresr.webtroopmanager.client.ui.cells.ParticipantCell;
import us.mooresr.webtroopmanager.client.ui.cells.PersonCell;
import us.mooresr.webtroopmanager.shared.EventParticipantSummary;
import us.mooresr.webtroopmanager.shared.PersonSummary;
import us.mooresr.webtroopmanager.shared.Privilege;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.shared.GwtEvent;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.cellview.client.CellList;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.view.client.CellPreviewEvent;
import com.google.gwt.view.client.DefaultSelectionEventManager;
import com.google.gwt.view.client.ListDataProvider;
import com.google.gwt.view.client.MultiSelectionModel;
import com.google.gwt.view.client.ProvidesKey;
import com.google.gwt.view.client.SelectionChangeEvent;
import com.google.gwt.view.client.SingleSelectionModel;

public class EventParticipantsViewImpl extends Composite implements EventParticipantsView {
	
	private static EventParticipantsUiBinder uiBinder = GWT.create(EventParticipantsUiBinder.class);

	interface EventParticipantsUiBinder extends UiBinder<Widget, EventParticipantsViewImpl> {
	}

	private Presenter presenter;
	
	private ListDataProvider<PersonSummary> personListDataProvider;
	private CellList<PersonSummary> personList;
	
	private ListDataProvider<EventParticipantSummary> participantListDataProvider;
	private CellList<EventParticipantSummary> participantList;
	
	private Set<PersonSummary> selectedPeople;
	private EventParticipantSummary selectedParticipants;
	
	@UiField
	Button okButton;
	
	@UiField
	Button cancelButton;
	
	@UiField
	Button addButton;
	
	@UiField
	Button removeButton;
	
	@UiField
	ScrollPanel peopleScroller;
	
	@UiField
	ScrollPanel participantScroller;
	
	@UiField
	Label participantName;
	
	@UiField
	CheckBox paidCheckBox;
	
	@UiField
	CheckBox permissionSlipCheckBox;
	
	@UiHandler("okButton")
	void onOKClick(ClickEvent e) {
		
		List<EventParticipantSummary> participants = participantListDataProvider.getList();
		
		// For some reason we can't serialize the list we get from the data provider
		ArrayList<EventParticipantSummary> serializableList = new ArrayList<EventParticipantSummary>();
		for (EventParticipantSummary ep : participants) {
			serializableList.add(ep);
		}
		
		presenter.storeEventParticipants(serializableList);
		
		presenter.goTo(new EventListPlace());
	}
	
	@UiHandler("cancelButton")
	void onCancelClick(ClickEvent e) {
		presenter.goTo(new EventListPlace());
		
	}
	
	@UiHandler("addButton")
	void onAddClick(ClickEvent e) {
		List<EventParticipantSummary> participantNames = participantListDataProvider.getList();
		List<PersonSummary> personNames = personListDataProvider.getList();
	
		for (PersonSummary selectedPerson : selectedPeople) {
			
		
			EventParticipantSummary ep = new EventParticipantSummary(null, presenter.getEventId(), selectedPerson.getId(), 
				false, false, selectedPerson.getFirstName(), selectedPerson.getLastName());
		
		
			participantNames.add(ep);
			participantList.getSelectionModel().setSelected(ep, false);
			personNames.remove(selectedPerson);
		}
		
		
		personList.setPageSize(personNames.size());		
		participantList.setPageSize(participantNames.size());
		
		selectedPeople.clear();
		addButton.setEnabled(false);
		
		
	}
	
	@UiHandler("removeButton")
	void onRemoveClick(ClickEvent e) {
		PersonSummary p = new PersonSummary(selectedParticipants.getPersonId(), selectedParticipants.getFirstName(),
				selectedParticipants.getLastName());
		
		List<EventParticipantSummary> participantNames = participantListDataProvider.getList();
		participantNames.remove(selectedParticipants);
		participantList.setPageSize(participantNames.size());
		
		List<PersonSummary> personNames = personListDataProvider.getList();
		personNames.add(p);
		personList.setPageSize(personNames.size());
		
		personList.getSelectionModel().setSelected(p, false);
		
		selectedParticipants = null;
		selectedParticpantChanged();
	}
	
	@UiHandler("paidCheckBox")
	void onPaidChange(ClickEvent e) {
		selectedParticipants.setPaid(paidCheckBox.getValue());
	}
	
	@UiHandler("permissionSlipCheckBox")
	void onPermissionChange(ClickEvent e) {
		selectedParticipants.setPermissionSlip(permissionSlipCheckBox.getValue());
	}
	
	public EventParticipantsViewImpl() {
		initWidget(uiBinder.createAndBindUi(this));
		
		ProvidesKey<PersonSummary> personKeyProvider = new ProvidesKey<PersonSummary>() {
			public Object getKey(PersonSummary item) {
				return (item == null) ? null : item.getId();
			}
		};
		
		personList = new CellList<PersonSummary>(new PersonCell(), personKeyProvider);
		personList.setSize("147px", "440px");
		
		final MultiSelectionModel<PersonSummary> selectionModel = 
			new MultiSelectionModel<PersonSummary>(personKeyProvider);
		personList.setSelectionModel(selectionModel);
		selectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler() {
			@Override
			public void onSelectionChange(SelectionChangeEvent event) {
				selectedPeople = selectionModel.getSelectedSet();
				selectedPersonChanged();		
			}			
		});
		
		peopleScroller.setWidget(personList);
		
		personListDataProvider = new ListDataProvider<PersonSummary>();
		personListDataProvider.addDataDisplay(personList);

		ProvidesKey<EventParticipantSummary> participantKeyProvider = new ProvidesKey<EventParticipantSummary>() {
			public Object getKey(EventParticipantSummary item) {
				return (item == null) ? null :item.getEventId().toString() + ":" + item.getPersonId().toString();
			}
		};
		
		participantList = new CellList<EventParticipantSummary>(new ParticipantCell());
		participantList.setSize("147px", "330px");
		
		final SingleSelectionModel<EventParticipantSummary> participantSelectionModel = 
			new SingleSelectionModel<EventParticipantSummary>(participantKeyProvider);
		participantList.setSelectionModel(participantSelectionModel);
		participantSelectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler() {

			@Override
			public void onSelectionChange(SelectionChangeEvent event) {
				selectedParticipants = participantSelectionModel.getSelectedObject();
				selectedParticpantChanged();
				
			}
			
		});
		participantScroller.setWidget(participantList);
		
		
		participantListDataProvider = new ListDataProvider<EventParticipantSummary>();
		participantListDataProvider.addDataDisplay(participantList);
		
		selectedPeople = null;
		selectedPersonChanged();
		
		selectedParticipants = null;
		selectedParticpantChanged();
			

		
	}
	

	@Override
	public void setPresenter(Presenter presenter) {
		this.presenter = presenter;		

	}

	@Override
	public void setCurrentParticipants(List<EventParticipantSummary> participants) {	
		List<EventParticipantSummary> providerList = participantListDataProvider.getList();
		providerList.clear();
		for (EventParticipantSummary p : participants) {
			providerList.add(p);
		}
		participantList.setPageSize(participants.size());
		selectedParticipants = null;
		selectedParticpantChanged();
		
	}

	@Override
	public void setPotentialParticipants(List<PersonSummary> people) {
		List<PersonSummary> providerList = personListDataProvider.getList();
		providerList.clear();
		for (PersonSummary p : people) {
			providerList.add(p);
		}
		personList.setPageSize(people.size());
		selectedPeople = null;
		selectedPersonChanged();
		
	}

	private void selectedParticpantChanged() {
		if (selectedParticipants == null) {
			participantName.setText("");
			paidCheckBox.setValue(false);
			paidCheckBox.setEnabled(false);
			permissionSlipCheckBox.setValue(false);
			permissionSlipCheckBox.setEnabled(false);
			removeButton.setEnabled(false);
		} else {
			participantName.setText(selectedParticipants.getDisplayName());
			paidCheckBox.setValue(selectedParticipants.getPaid());
			paidCheckBox.setEnabled(true);
			permissionSlipCheckBox.setValue(selectedParticipants.getPermissionSlip());
			permissionSlipCheckBox.setEnabled(true);
			if (presenter.isAllowed(Privilege.REMOVE_PERSON_FROM_EVENT, selectedParticipants.getPersonId())) {
				removeButton.setEnabled(true);
			} else {
				removeButton.setEnabled(false);
			}
		}
	}
	
	private void selectedPersonChanged() {
		/* Start out assuming that the add button should be enabled.  It will be
		 * disabled if any of the following are true:
		 * - selectedPeople is null
		 * - selectedPeople is empty
		 * - permission to add fails for any person in the selectedPeople list
		 */
		Boolean canAdd = true;
		

		if ((selectedPeople == null) || (selectedPeople.size() == 0)) {
			canAdd = false;
		} else {
			for (PersonSummary p : selectedPeople) {
				if (presenter.isAllowed(Privilege.ADD_PERSON_TO_EVENT, p.getId()) == false) {
					canAdd = false;
				}
			}
		}
		
		addButton.setEnabled(canAdd);
	}

}
